package com.seven.ezpermissions

import android.content.pm.PackageManager
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.seven.ezpermissions.helper.PermissionsHelper

/**
 * Single permission request
 * @author seven.xie
 * @date 2020/7/10 14:17
 * email: se7en.xie@qq.com
 */
class PermissionRequest private constructor(
    internal val helper: PermissionsHelper<*>,
    internal val permissions: Array<out String>,
    internal val requestCode: Int,
    internal val rationale: String,
    internal val positiveButton: String,
    internal val negativeButton: String,
    internal var onGrantedCallback: OnGrantedCallback?,
    internal var onDeniedCallback: OnDeniedCallback?
) {

    fun addLifecycleObserver(observer: LifecycleObserver) {
        helper.addLifecycleObserver(observer)
    }

    fun onStateChanged(
        source: LifecycleOwner,
        event: Lifecycle.Event,
        observer: LifecycleObserver,
        callback: OnDestroyEvent
    ) {
        helper.onStateChanged(source, event, observer, callback)
    }

    fun request() {
        helper.request(
            rationale, positiveButton, negativeButton, requestCode, permissions, onDeniedCallback
        )
    }

    fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        val denied = mutableListOf<String>()
        for (i in grantResults.indices) {
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                denied.add(permissions[i])
            }
        }
        if (denied.isEmpty()) {
            // all permissions granted
            onGrantedCallback?.invoke(requestCode)
        } else {
            // report the denied permissions
            onDeniedCallback?.invoke(requestCode, denied)
        }
    }

    class Builder {

        private val helper: PermissionsHelper<*>
        private val requestCode: Int
        private val permissions: Array<out String>

        private var rationale: String? = null
        private var positiveButton: String? = null
        private var negativeButton: String? = null

        private var onGrantedCallback: OnGrantedCallback? = null
        private var onDeniedCallback: OnDeniedCallback? = null

        constructor(activity: AppCompatActivity, permissions: Array<out String>, requestCode: Int) {
            helper = PermissionsHelper.newInstance(activity)
            this.requestCode = requestCode
            this.permissions = permissions
        }

        constructor(fragment: Fragment, permissions: Array<out String>, requestCode: Int) {
            helper = PermissionsHelper.newInstance(fragment)
            this.requestCode = requestCode
            this.permissions = permissions
        }

        fun setRationale(rationale: String?): Builder {
            this.rationale = rationale
            return this
        }

        fun setRationale(@StringRes rationale: Int): Builder {
            this.rationale = helper.context?.getString(rationale)
            return this
        }

        fun setPositiveButton(positiveButton: String?): Builder {
            this.positiveButton = positiveButton
            return this
        }

        fun setPositiveButton(@StringRes positiveButton: Int): Builder {
            this.positiveButton = helper.context?.getString(positiveButton)
            return this
        }

        fun setNegativeButton(negativeButton: String?): Builder {
            this.negativeButton = negativeButton
            return this
        }

        fun setNegativeButton(@StringRes negativeButton: Int): Builder {
            this.negativeButton = helper.context?.getString(negativeButton)
            return this
        }

        fun onGranted(callback: OnGrantedCallback?): Builder {
            this.onGrantedCallback = callback
            return this
        }

        fun onDenied(callback: OnDeniedCallback?): Builder {
            this.onDeniedCallback = callback
            return this
        }

        fun build(): PermissionRequest {
            if (rationale == null) {
                rationale = helper.context?.getString(R.string.ez_permissions_rationale_ask)
            }
            if (positiveButton == null) {
                positiveButton = helper.context?.getString(R.string.ez_permissions_ok)
            }
            if (negativeButton == null) {
                negativeButton = helper.context?.getString(R.string.ez_permissions_cancel)
            }

            return PermissionRequest(
                helper = helper,
                permissions = permissions,
                requestCode = requestCode,
                rationale = rationale ?: "",
                positiveButton = positiveButton ?: "",
                negativeButton = negativeButton ?: "",
                onGrantedCallback = onGrantedCallback,
                onDeniedCallback = onDeniedCallback
            )
        }
    }
}